package com.kefu.call.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.kefu.basic.mapper.BasicRptMapper;
import com.kefu.basic.model.BasicRpt;
import com.kefu.basic.model.BasicRptCol;
import com.kefu.call.mapper.CallIvrTrailMapper;
import com.kefu.call.mapper.CallStartMapper;
import com.kefu.call.model.CallIvrTrail;
import com.kefu.call.model.CallStart;
import com.kefu.call.vo.*;
import com.kefu.call.vo.CallStartVo.CallStartRptVo;
import com.kefu.common.context.KefuContext;
import com.kefu.common.service.AbstractKefuService;
import com.kefu.common.util.Assert;
import com.kefu.common.util.DateUtils;
import com.kefu.common.util.DivUtil;
import com.kefu.common.util.JacksonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CallStartService extends AbstractKefuService<CallStart> {
    @Resource
    private BasicRptMapper basicRptMapper;
    @Resource
    private CallStartMapper callStartMapper;

    @Resource
    private CallIvrTrailMapper callIvrTrailMapper;
    /**
     * 呼入纪录
     */
    public Page<Map<String, Object>> callStartRecord(CallStartRptVo search) {
        Assert.isEmpty(search.getRptId(), "未选择方案");
        String rptId = search.getRptId();
        BasicRpt rpt = basicRptMapper.selectByPrimaryKey(rptId);
        Assert.isNull(rpt, "自定义字段已被删除!");
        String cols = rpt.getRptFields();
        Assert.isEmpty(cols, "未设置查询字段");
        List<BasicRptCol> basicRptCols = JSONUtil.parseArray(cols).toList(BasicRptCol.class);
        String sql = basicRptCols.stream().map(BasicRptCol::getCodeFunction).collect(Collectors.joining(","));
        Assert.isEmpty(sql, "未设置显示字段内容！");
        Page<Map<String, Object>> page = new Page<>(search.getPageNo(), search.getPageSize(), true);
        QueryWrapper<CallStart> wrapper = Wrappers.query();
        wrapper.eq("Company", KefuContext.getTid());
        wrapper.eq(StrUtil.isNotBlank(search.getAgentId()), "CCAgent", search.getAgentId());
        wrapper.ge(Objects.nonNull(search.getCallStartTime()), "IvrStartTime",
                        Timestamp.valueOf(DateUtil.format(new Date(search.getCallStartTime()), "yyyy-MM-dd HH:mm:ss")));
        wrapper.le(Objects.nonNull(search.getCallEndTime()), "IvrStartTime", Timestamp.valueOf(DateUtil.format(new Date(search.getCallEndTime()), "yyyy-MM-dd HH:mm:ss")));
        page.setTotal(callStartMapper.selectCount(wrapper));
        wrapper.select(sql);
        wrapper.last("LIMIT " + search.getPageSize() + " OFFSET " + (search.getPageSize() * (search.getPageNo() - 1)));
        List<Map<String, Object>> mapList = callStartMapper.selectMaps(wrapper);
        page.setRecords(mapList);
        return page;
    }

    /**
     * 导出呼入纪录
     */
    public List<Object[]> callStartRecordExport(CallStartVo.CallStartRptVo search) {
        Assert.isNull(search.getCallStartTime(), "未选择开始时间！");
        BasicRpt rpt = basicRptMapper.selectByPrimaryKey(search.getRptId());
        Assert.isNull(rpt, "自定义字段已被删除!");
        String rptFields = rpt.getRptFields();
        Assert.isEmpty(rptFields, "未设置显示字段");
        List<BasicRptCol> basicRptCols = JSONUtil.parseArray(rptFields).toList(BasicRptCol.class);
        search.setPageNo(1);
        search.setPageSize(50000);
        Page<Map<String, Object>> page = callStartRecord(search);
        List<Object[]> exportList = new ArrayList<>();
        Object[] title = new Object[basicRptCols.size()];
        for (int i = 0; i < basicRptCols.size(); i++) {
            title[i] = msg(basicRptCols.get(i).getCodeName());
        }
        exportList.add(title);
        for (Map<String, Object> i : page.getRecords()) {
            Object[] row = new Object[basicRptCols.size()];
            for (int j = 0; j < basicRptCols.size(); j++) {
                Object cell = i.get(basicRptCols.get(j).getCodeId());
                row[j] = cell;
            }
            exportList.add(row);
        }
        return exportList;
    }

    public CallStartIvrRptResp callStartIvrRpt(CallStartIvrRptVo search) {
        CallStartIvrRptResp resp = new CallStartIvrRptResp();
        QueryWrapper<CallIvrTrail> wrapper = Wrappers.query();
        wrapper.eq("ivroid", search.getIvrOid());
        List<String> viewsOidList = search.getViewsOidList();
        if (CollUtil.isNotEmpty(viewsOidList)) {
            wrapper.in("nodeid", viewsOidList);
        }
        Long callStartTime = search.getCallStartTime();
        if (Objects.nonNull(callStartTime)) {
            String startTime = DateUtil.format(new Date(callStartTime), "yyyy-MM-dd HH:mm:ss");
            wrapper.ge("createtime", startTime);
        }
        Long callEndTime = search.getCallEndTime();
        if (Objects.nonNull(callEndTime)) {
            String endTime = DateUtil.format(new Date(callEndTime), "yyyy-MM-dd HH:mm:ss");
            wrapper.le("createtime", endTime);
        }
        Long totalCount = callIvrTrailMapper.selectCount(wrapper);
        if (totalCount > 0 ) {
            wrapper.select("nodetype as name, COUNT(*) AS count");
            wrapper.groupBy("nodetype");
            List<Map<String, Object>> list = callIvrTrailMapper.selectMaps(wrapper);
            if (CollUtil.isNotEmpty(list)) {
                list.forEach(resultMap -> {
                    Object count = resultMap.get("count");
                    if (Objects.nonNull(count)) {
                        resultMap.put("rate", DivUtil.percent(Convert.toLong(count), totalCount));
                    }
                });
            }
            resp.setList(list);
            log.info("按业务类型统计: {}, {}", totalCount, JacksonUtil.toString(list));
        }
        return resp;
    }

    public List<Object[]> callStartRptExport(CallStartIvrRptVo search) {
        List<Object[]> exportList = new ArrayList<>();
        Object[] title = {msg("咨询分类"), msg("来电数量"), msg("占比")};
        CallStartIvrRptResp resp = callStartIvrRpt(search);
        exportList.add(title);
        if (CollUtil.isNotEmpty(resp.getList())) {
            for (Map<String, Object> resultMap : resp.getList()) {
                Object busiName = resultMap.get("name");
                Object busiCount = resultMap.get("count");
                Object busiRate = resultMap.get("rate");
                Object[] row = {busiName, busiCount, busiRate};
                exportList.add(row);
            }
            Object[] row = {"合计", resp.getTotalCount(), "100%"};
            exportList.add(row);
        }
        return exportList;
    }

    public List<Map<String, Object>> callStartProvinceRpt(CallStartProvinceRptVo search) {
        List<Map<String, Object>> list = null;
        QueryWrapper<CallStart> wrapper = Wrappers.query();
        wrapper.eq("company", KefuContext.getTid());
        if (Objects.nonNull(search.getCallStartTime())) {
            wrapper.ge("ivrstarttime", DateUtil.format(new Date(search.getCallStartTime()), "yyyy-MM-dd HH:mm:ss"));
        }
        if (Objects.nonNull(search.getCallEndTime())) {
            wrapper.le("ivrstarttime", DateUtil.format(new Date(search.getCallEndTime()), "yyyy-MM-dd HH:mm:ss"));
        }
        Long totalCount = callStartMapper.selectCount(wrapper);
        if (totalCount > 0) {
            wrapper.select("calling_province as name, COUNT(*) AS count");
            wrapper.groupBy("calling_province");
            list = callStartMapper.selectMaps(wrapper);
            Map<String, Object> map = new HashMap<>();
            map.put("name", "其他");
            Long otherCount = 0l;
            for (Map<String, Object> resultMap :
                    list) {
                String key = Convert.toStr(resultMap.get("name"));
                if (StrUtil.isBlank(key)) {
                    otherCount += Convert.toLong(resultMap.get("count"));
                } else {
                    Object count = resultMap.get("count");
                    if (Objects.nonNull(count)) {
                        resultMap.put("rate", DivUtil.percent(Convert.toLong(count), totalCount));
                    }
                }
            }
            map.put("count", otherCount);
            map.put("rate", DivUtil.percent(Convert.toLong(otherCount), totalCount));
            list.add(map);
            log.info("按省份统计呼入信息: {}, {}", totalCount, JacksonUtil.toString(list));
        }
        return list;
    }

    public List<Object[]> callStartProvinceRptExport(CallStartProvinceRptVo search) {
        List<Object[]> exportList = new ArrayList<>();
        Object[] title = {msg("省份"), msg("占比")};
        List<Map<String, Object>> list = callStartProvinceRpt(search);
        exportList.add(title);
        if (CollUtil.isNotEmpty(list)) {
            for (Map<String, Object> resultMap : list) {
                Object name = resultMap.get("name");
                Object rate = resultMap.get("rate");
                Object[] row = {name, rate};
                exportList.add(row);
            }
        }
        return exportList;
    }

    /**
     * 地域分布列表
     * @param search
     * @return
     */
    public List<Map<String, Object>> regionRpt(CallStartRegionRptVo search) {
        QueryWrapper<CallStart> wrapper = Wrappers.query();
        wrapper.select("(CASE WHEN calling_province IS NULL OR calling_province = '' THEN '未知号段' ELSE calling_province END) AS callingProvince," +
                "COUNT(*) AS totalCount," +
                "SUM(CASE WHEN ccagentansweredtime IS NOT NULL THEN 1 ELSE 0 END) AS dealingCount," +
                "SUM(CASE WHEN ccofferingtime IS NOT NULL AND ccagentansweredtime IS NULL THEN 1 ELSE 0 END) AS notDealCount," +
                "SUM(CASE WHEN queuestarttime IS NOT NULL AND ccofferingtime IS NULL THEN 1 ELSE 0 END) AS queueLeakCount," +
                "SUM(talktime) AS incomingTimeLength," +
                "SUM(calleeringdurationtime) AS incomingRingingTimeLength ");
        wrapper.eq("company", KefuContext.getTid());
        if (CollUtil.isNotEmpty(search.getGroupIds())) {
            wrapper.in("org", search.getGroupIds());
        }
        if (Objects.nonNull(search.getQueryTimeStart())) {
            wrapper.ge("ivrstarttime", DateUtils.dateTimeFormat(search.getQueryTimeStart()));
        }
        if (Objects.nonNull(search.getQueryTimeEnd())) {
            wrapper.le("ivrstarttime", DateUtils.dateTimeFormat(search.getQueryTimeEnd()));
        }
        wrapper.groupBy("calling_province");
        List<Map<String, Object>> mapList = callStartMapper.selectMaps(wrapper);
        return mapList;
    }

    /**
     * 地域分布导出
     * @param search
     * @return
     */
    public List<Object[]> regionRptExport(CallStartRegionRptVo search) {
        List<Object[]> exportList = new ArrayList<>();
        Object[] title = {msg("省份"), msg("总数"),msg("接听数"),
                msg("振铃未接听数"), msg("排队放弃数"),
                msg("通话时长(秒)"), msg("呼入振铃总时长(秒)")};
        List<Map<String, Object>> list = regionRpt(search);
        exportList.add(title);
        if (CollUtil.isNotEmpty(list)) {
            for (Map<String, Object> resp : list) {
                Object[] row = {resp.get("callingprovince"), resp.get("totalcount"),
                        resp.get("dealingcount"), resp.get("notdealcount")
                        , resp.get("queueleakcount"),
                        resp.get("incomingtimelength"), resp.get("incomingringingtimelength")};
                exportList.add(row);
            }
        }
        return exportList;
    }
}
